package com.sunchangpeng.wechat.mp.mass;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.annotation.JSONField;
import com.sunchangpeng.wechat.core.WechatClient;
import com.sunchangpeng.wechat.mp.EndpointProvider;
import com.sunchangpeng.wechat.mp.MpAppSetting;
import com.sunchangpeng.wechat.mp.MpWechatClientFactory;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.util.List;

public class MassMessages {
    private WechatClient wechatClient;

    public void setWechatClient(WechatClient wechatClient) {
        this.wechatClient = wechatClient;
    }

    public static MassMessages with(MpAppSetting appSetting) {
        MassMessages massMessages = new MassMessages();
        massMessages.setWechatClient(MpWechatClientFactory.getInstance().with(appSetting));
        return massMessages;
    }

    /**
     * 群发图文消息消息给所有人
     */
    public long mpNews(String mpNews) {
        return sendAll(new Filter(true, null), "mpnews", mpNews);
    }

    /**
     * 群发图文消息给指定群组的人
     */
    public long mpNews(int tagId, String mpNews) {
        return sendAll(new Filter(false, tagId), "mpnews", mpNews);
    }

    /**
     * 群发图文消息给指定的人
     */
    public long mpNews(List<String> openIds, String mpNews) {
        return send(openIds, "mpnews", mpNews);
    }

    /**
     * 预览图文消息
     */
    public long mpNewsPreview(String wxName, String openId, String mpNews) {
        return preview(wxName, openId, "mpnews", mpNews);
    }

    /**
     * 群发文本消息, 所有人
     */
    public long text(String text) {
        return sendAll(new Filter(true, null), "text", text);
    }

    /**
     * 指定分组群发文本消息
     */
    public long text(int tagId, String text) {
        return sendAll(new Filter(false, tagId), "text", text);
    }

    /**
     * 发文本消息给指定人
     */
    public long text(List<String> openIds, String text) {
        return send(openIds, "text", text);
    }

    /**
     * 预览文本消息
     */
    public long     textPreview(String wxName, String openId, String text) {
        return preview(wxName, openId, "text", text);
    }

    /**
     * 群发语音消息，所有人
     */
    public long voice(String voice) {
        return sendAll(new Filter(true, null), "voice", voice);
    }

    /**
     * 群发语音消息给指定群组
     */
    public long voice(int tagId, String voice) {
        return sendAll(new Filter(false, tagId), "voice", voice);
    }

    /**
     * 群发语音消息给指定人
     */
    public long voice(List<String> openIds, String voice) {
        return send(openIds, "voice", voice);
    }

    /**
     * 预览语音消息
     */
    public long voicePreview(String wxName, String openId, String voice) {
        return preview(wxName, openId, "voice", voice);
    }

    /**
     * 群发图片消息给所有人
     */
    public long image(String image) {
        return sendAll(new Filter(true, null), "image", image);
    }

    /**
     * 群发图片消息给指定群组的人
     */
    public long image(int tagId, String image) {
        return sendAll(new Filter(false, tagId), "image", image);
    }

    /**
     * 群发图片消息给指定的人
     */
    public long image(List<String> openIds, String image) {
        return send(openIds, "image", image);
    }

    /**
     * 预览图片消息
     */
    public long imagePreview(String wxName, String openId, String image) {
        return preview(wxName, openId, "image", image);
    }

    /**
     * 群发卡券给所有人
     *
     * @param wxcard
     * @return
     */
    public long card(String wxcard) {
        return sendAll(new Filter(true, null), "wxcard", wxcard);
    }

    /**
     * 群发卡券给指定分组的人
     */
    public long card(int tagId, String wxcard) {
        return sendAll(new Filter(false, tagId), "wxcard", wxcard);
    }

    /**
     * 群发卡券给指定的人
     */
    public long card(List<String> openIds, String wxcard) {
        return send(openIds, "wxcard", wxcard);
    }

    /**
     * 预览图片消息
     */
    public long cardPreview(String wxName, String openId, String wxcard) {
        return preview(wxName, openId, "wxcard", wxcard);
    }

    /**
     * 群发视频消息给所有人
     */
    public long video(String mediaId, String title, String desc) {
        return sendAll(new Filter(true, null), "mpvideo", videoUpload(mediaId, title, desc));
    }

    /**
     * 群发视频消息给特定分组的人
     */
    public long video(int tagId, String mediaId, String title, String desc) {
        return sendAll(new Filter(false, tagId), "mpvideo", videoUpload(mediaId, title, desc));
    }

    /**
     * 群发视频消息给特定用户
     */
    public long video(List<String> openIds, String mediaId, String title, String desc) {
        return send(openIds, "mpvideo", videoUpload(mediaId, title, desc));
    }

    /**
     * 群发视频预览给特定用户
     */
    public long videoPreview(String wxName, String openId, String mediaId, String title, String desc) {
        return preview(wxName, openId, "mpvideo", videoUpload(mediaId, title, desc));
    }

    /**
     * 删除群发消息
     */
    public void delete(long msgId) {
        String url = EndpointProvider.get("url.mass.message.delete");
        wechatClient.getTextWithToken(url, JSON.toJSONString(new JSONObject().fluentPut("msg_id", msgId)));
    }

    /**
     * 查询群发消息状态
     */
    public MessageStatus status(long msgId) {
        String url = EndpointProvider.get("url.mass.message.status");
        String response = wechatClient.getTextWithToken(url, JSON.toJSONString(new JSONObject().fluentPut("msg_id", msgId)));
        return JSON.parseObject(response, MessageStatus.class);
    }

    /**
     * 获取群发速度
     */
    public Speed getSpeed() {
        String url = EndpointProvider.get("url.mass.message.speed.get");
        String response = wechatClient.getTextWithToken(url);
        return JSON.parseObject(response, Speed.class);
    }


    /**
     * 设置群发速度
     * 0	80w/分钟
     * 1	60w/分钟
     * 2	45w/分钟
     * 3	30w/分钟
     * 4	10w/分钟
     */
    public void setSpeed(int speed) {
        String url = EndpointProvider.get("url.mass.message.speed.set");
        wechatClient.getTextWithToken(url, JSON.toJSONString(new JSONObject().fluentPut("speed", speed)));
    }

    private String videoUpload(String mediaId, String title, String desc) {
        String uploadUrl = EndpointProvider.get("url.mass.message.video.upload");
        JSONObject uploadRequest = new JSONObject()
                .fluentPut("media_id", mediaId)
                .fluentPut("title", title)
                .fluentPut("description", desc);
        String response = wechatClient.getTextWithToken(uploadUrl, JSON.toJSONString(uploadRequest));
        return JSON.parseObject(response).getString("media_id");
    }

    private JSONObject initMessage(String msgType, String message, boolean sendReprint, String clientMsgId) {
        JSONObject msg = new JSONObject()
                .fluentPut("msgtype", msgType);

        if ("wxcard".equalsIgnoreCase(msgType)) {
            msg.put(msgType, new Card(message));
            return msg;

        }

        if ("text".equalsIgnoreCase(msgType)) {
            msg.put(msgType, new Text(message));
            return msg;
        }

        msg.put(msgType, new Media(message));

        if ("mpnews".equalsIgnoreCase(msgType)) {
            if (sendReprint) {
                msg.put("send_ignore_reprint", 1);
            }
        }

        if (StringUtils.isNotBlank(clientMsgId)) {
            msg.put("clientmsgid", clientMsgId);
        }

        return msg;
    }

    public long sendAll(Filter filter, String msgType, String message) {
        return sendAll(filter, msgType, message, false, null);
    }

    public long sendAll(Filter filter, String msgType, String message, String clientMsgId) {
        return sendAll(filter, msgType, message, false, clientMsgId);
    }

    public long sendAll(Filter filter, String msgType, String message, boolean sendReprint, String clientMsgId) {
        String url = EndpointProvider.get("url.mass.message.sendall");
        JSONObject request = initMessage(msgType, message, sendReprint, clientMsgId)
                .fluentPut("filter", filter);
        String response = wechatClient.getTextWithToken(url, JSON.toJSONString(request));
        return JSON.parseObject(response, Result.class).getMsgId();
    }

    public long send(List<String> openIds, String msgType, String message) {
        return send(openIds, msgType, message, false, null);
    }

    public long send(List<String> openIds, String msgType, String message, String clientMsgId) {
        return send(openIds, msgType, message, false, clientMsgId);
    }

    public long send(List<String> openIds, String msgType, String message, boolean sendReprint, String clientMsgId) {
        String url = EndpointProvider.get("url.mass.message.send");
        JSONObject request = initMessage(msgType, message, sendReprint, clientMsgId)
                .fluentPut("touser", openIds);
        String response = wechatClient.getTextWithToken(url, JSON.toJSONString(request));
        return JSON.parseObject(response, Result.class).getMsgId();
    }

    //每日调用次数有限制（100次），请勿滥用
    public long preview(String wxName, String openId, String msgType, String message) {
        String url = EndpointProvider.get("url.mass.message.preview");
        JSONObject request = initMessage(msgType, message, false, null);

        if (StringUtils.isNotBlank(wxName)) {
            request.put("towxname", wxName);
        }

        if (StringUtils.isNotBlank(openId)) {
            request.put("touser", openId);
        }

        String response = wechatClient.getTextWithToken(url, JSON.toJSONString(request));
        return JSON.parseObject(response, Result.class).getMsgId();
    }


    @Data
    public static class Filter {
        @JSONField(name = "is_to_all")
        private boolean toALl;

        @JSONField(name = "tag_id")
        private Integer tagId;

        public Filter(boolean toALl, Integer tagId) {
            this.toALl = toALl;
            this.tagId = tagId;
        }
    }

    @Data
    public static class Result {
        @JSONField(name = "msg_id")
        private long msgId;
        @JSONField(name = "msg_data_id")
        private long msgDataId;
    }


    @Data
    public static class Media {
        @JSONField(name = "media_id")
        private String mediaId;

        public Media(String mediaId) {
            this.mediaId = mediaId;
        }
    }

    @Data
    public static class Card {
        @JSONField(name = "card_id")
        private String cardId;

        public Card(String cardId) {
            this.cardId = cardId;
        }
    }

    @Data
    public static class Text {
        private String content;

        public Text(String content) {
            this.content = content;
        }
    }

    @Data
    public static class MessageStatus {
        @JSONField(name = "msg_id")
        private Long msgId;
        @JSONField(name = "msg_status")
        private String msgStatus;
    }

    @Data
    public static class Speed {
        private Integer speed;
        private Integer realspeed;
    }
}
